﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using Qiang.Data;
using Qiang.Styles;
using Qiang.Topology.Geometries;
using Point = System.Drawing.Point;

namespace Qiang.Controls
{
    public class MapVectorLayer : VectorLayer, IMapVectorLayer
    {

        #region 初始化

        /// <summary>
        /// 用于map控件显示的自定义矢量图层
        /// </summary>
        public MapVectorLayer(VectorSet dataset)
            : base(dataset)
        {
            this.Selectable = true;
        }



        #endregion


        #region 绘制方法

        public virtual void DrawRegion(MapDrawArgs args, IExtent region)
        {
            Graphics g = args.MapGraphics;

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;                       

            DrawPolygon(args, region);

            DrawSegment(args, region);

            DrawNode(args, region);

            DrawLabel(args, region);
        }

        void DrawNode(MapDrawArgs args, IExtent region)
        {
            bool selected = false;
            for (int state = 0; state < 2; state++)
            {
                if (state == 0) selected = false;
                else selected = true;
                IEnumerable<KeyValuePair<IShape, ShapeState>> Nodes =
                    from item in Filter.VectorStates
                    where item.Value.IsSelected == selected && item.Key.ShapeType == ShapeType.Node
                    select item;
                foreach (KeyValuePair<IShape, ShapeState> item in Nodes)
                {
                    INodeShape node = item.Key as INodeShape;
                    if (region.Contains(node.Point) == false) continue;
                    Point pt = args.ProjToPixel(node.Point);
                    if (selected)
                    {
                        Filter.VectorStates[node].SelectionSymbol.NodeSymbol.Draw(args.MapGraphics, pt);
                    }
                    else
                    {
                        Filter.VectorStates[node].Symbol.NodeSymbol.Draw(args.MapGraphics, pt);
                    }
                }
            }
        }

        void DrawSegment(MapDrawArgs args, IExtent region)
        {
            bool selected = false;
            for (int state = 0; state < 2; state++)
            {
                if (state == 0) selected = false;
                else selected = true;
                IEnumerable<KeyValuePair<IShape, ShapeState>> Segments =
                    from item in Filter.VectorStates
                    where item.Value.IsSelected == selected && item.Key.ShapeType == ShapeType.Segment
                    select item;
                foreach(KeyValuePair<IShape ,ShapeState> item in Segments)
                {
                    ISegmentShape segment = item.Key as ISegmentShape;
                    List<Point> ptLst = new List<Point>();
                    ptLst.Add(args.ProjToPixel(segment.StartNode.Point));
                    foreach (VertexShape vertex in segment.VertexCollection)
                    {
                        Point pt = args.ProjToPixel(vertex.Point);
                        ptLst.Add(pt);
                    }
                    ptLst.Add(args.ProjToPixel(segment.EndNode.Point));

                    //SoutherlandHodgman ClipTool = new SoutherlandHodgman(new Rectangle(region.MinX, region.MinY, region.Width, region.Height));

                    GraphicsPath path = new GraphicsPath();
                    path.AddLines(ptLst.ToArray());

                    if (selected)
                    {
                        Filter.VectorStates[segment].SelectionSymbol.LineSymbol.DrawPath(args.MapGraphics, path);
                    }
                    else
                    {
                        Filter.VectorStates[segment].Symbol.LineSymbol.DrawPath(args.MapGraphics, path);
                    }
                }
            }
        }

        void DrawPolygon(MapDrawArgs args, IExtent region)
        {
            bool selected = false;
            for (int state = 0; state < 2; state++)
            {
                if (state == 0) selected = false;
                else selected = true;
                IEnumerable<KeyValuePair<IShape, ShapeState>> Polygons = 
                    from item in Filter.VectorStates 
                    where item.Value.IsSelected == selected && item.Key.ShapeType == ShapeType.Polygon 
                    select item;                
                foreach (KeyValuePair<IShape,ShapeState> item in Polygons)
                {
                    IPolygonShape polygon = item.Key as IPolygonShape;
                    List<Point> ShellPts = new List<Point>();
                    foreach (DirectionalSegment segment in polygon.Shell.SegmentCollection)
                    {
                        List<Point> temLst = new List<Point>();
                        if (segment.Derection == SegmentDirection.Left)
                        {
                            temLst.Add(args.ProjToPixel(segment.Segment.StartNode.Point));
                            foreach (VertexShape pt in segment.Segment.VertexCollection)
                            {
                                temLst.Add(args.ProjToPixel(pt.Point));
                            }
                            ShellPts.AddRange(temLst.ToArray());
                        }
                        else
                        {
                            foreach (VertexShape pt in segment.Segment.VertexCollection)
                            {
                                temLst.Add(args.ProjToPixel(pt.Point));
                            }
                            temLst.Add(args.ProjToPixel(segment.Segment.EndNode.Point));
                            temLst.Reverse();

                            ShellPts.AddRange(temLst.ToArray());
                        }
                    }
                    GraphicsPath path = new GraphicsPath();
                    path.AddPolygon(ShellPts.ToArray());
                    Region shell = new Region(path);

                    foreach (IPart hole in polygon.Holes)
                    {
                        List<Point> HolePts = new List<Point>();
                        foreach (DirectionalSegment segment in hole.SegmentCollection)
                        {
                            List<Point> temLst = new List<Point>();
                            if (segment.Derection == SegmentDirection.Right)
                            {
                                temLst.Add(args.ProjToPixel(segment.Segment.StartNode.Point));
                                foreach (VertexShape pt in segment.Segment.VertexCollection)
                                {
                                    temLst.Add(args.ProjToPixel(pt.Point));
                                }
                                HolePts.AddRange(temLst.ToArray());
                            }
                            else
                            {
                                foreach (VertexShape pt in segment.Segment.VertexCollection)
                                {
                                    temLst.Add(args.ProjToPixel(pt.Point));
                                }
                                temLst.Add(args.ProjToPixel(segment.Segment.EndNode.Point));
                                temLst.Reverse();
                                HolePts.AddRange(temLst.ToArray());
                            }
                        }
                        path = new GraphicsPath();
                        path.AddPolygon(HolePts.ToArray());
                        Region holeRegion = new Region(path);
                        shell.Exclude(holeRegion);
                    }

                    if (selected == false)
                    {
                        Filter.VectorStates[polygon].Symbol.PolygonSymbol.FillRegion(args.MapGraphics, shell);
                    }
                    else
                    {
                        Filter.VectorStates[polygon].SelectionSymbol.PolygonSymbol.FillRegion(args.MapGraphics, shell);
                    }
                    path.Dispose();
                }
            }
        }

        void DrawLabel(MapDrawArgs args, IExtent region)
        {
            if (IsShowLabel == false) return; 
            foreach (IShape shp in Dataset.ShapeList)
            {
                IGeometry geometry = shp.ToGeometry();
                Point position = args.ProjToPixel(geometry.Centroid.Coordinate);
                Filter.VectorStates[shp].Symbol.LabelSymbol.DrawString(args.MapGraphics, shp.ID, position);
            }
        }

        #endregion


        public INodeShape TopologyPoint(MapControl map, Point pt)
        {
            if (this.Dataset == null) return null;
            if (map == null) return null;

            Rectangle rect = new Rectangle(pt.X - 3, pt.Y - 3, 6, 6);

            foreach (INodeShape node in this.Dataset.ShapeList.Where(n => n.ShapeType == ShapeType.Node))
            {
                Point nodePt = map.ProjToPixel(node.Point);
                if (rect.Contains(nodePt) == true)
                {
                    return node;
                }
            }

            return null;
        }


        public bool CheckPointForMove(Extent ext, ref Coordinate MovePoint, ref List<Coordinate> relatedPoints)
        {
            foreach (INodeShape node in this.Selection.ToList().Where(n => n.ShapeType == ShapeType.Node))
            {
                if (ext.Contains(node.Point))
                {
                    MovePoint = node.Point;

                    foreach (ISegmentShape segment in node.SegmentCollection)
                    {
                        if (segment.StartNode.Equals(node))
                        {
                            if (segment.VertexCollection.Count > 0)
                            {
                                relatedPoints.Add(segment.VertexCollection[0].Point);
                            }
                            else
                            {
                                relatedPoints.Add(segment.EndNode.Point);
                            }
                        }
                        if (segment.EndNode.Equals(node))
                        {
                            if (segment.VertexCollection.Count > 0)
                            {
                                relatedPoints.Add(segment.VertexCollection[segment.VertexCollection.Count - 1].Point);
                            }
                            else
                            {
                                relatedPoints.Add(segment.StartNode.Point);
                            }
                        }
                    }

                    return true;
                }
            }


            foreach (IVertexShape vertex in this.Selection.ToList().Where(v => v.ShapeType == ShapeType.Vertex))
            {
                if (ext.Contains(vertex.Point))
                {
                    MovePoint = vertex.Point;

                    for (int i = 0; i < vertex.ParentSegment.VertexCollection.Count; i++)
                    {
                        if (vertex.Equals(vertex.ParentSegment.VertexCollection[i]))
                        {
                            if (i == 0)
                            {
                                relatedPoints.Add(vertex.ParentSegment.StartNode.Point);
                                if (i == vertex.ParentSegment.VertexCollection.Count - 1)
                                {
                                    relatedPoints.Add(vertex.ParentSegment.EndNode.Point);
                                }
                                else
                                {
                                    relatedPoints.Add(vertex.ParentSegment.VertexCollection[i + 1].Point);
                                }
                            }
                            else if (i == vertex.ParentSegment.VertexCollection.Count - 1)
                            {
                                relatedPoints.Add(vertex.ParentSegment.VertexCollection[i - 1].Point);
                                relatedPoints.Add(vertex.ParentSegment.EndNode.Point);
                            }
                            else
                            {
                                relatedPoints.Add(vertex.ParentSegment.VertexCollection[i - 1].Point);
                                relatedPoints.Add(vertex.ParentSegment.VertexCollection[i + 1].Point);
                            }
                            break;
                        }
                    }


                    return true;
                }
            }


            return false;
        }


    }
}
